home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
68kdis.zip
/
ALLOC.C
next >
Wrap
C/C++ Source or Header
|
1988-12-03
|
6KB
|
337 lines
/*
* SCCS: @(#)alloc.c 1.2 11/2/84 14:17:20
* Allocate space etc.
*
***********************************************************************
* This software is copyright of
*
* John M Collins
* 47 Cedarwood Drive
* St Albans
* Herts, AL4 0DN
* England +44 727 57267
*
* and is released into the public domain on the following conditions:
*
* 1. No free maintenance will be guaranteed.
* 2. Nothing may be based on this software without
* acknowledgement, including incorporation of this
* notice.
*
* Notwithstanding the above, the author welcomes correspondence and bug
* fixes.
***********************************************************************
*/
#include <stdio.h>
#include <a.out.h>
#include <setjmp.h>
#include <ldfcn.h>
#include "unc.h"
#define STINC 10
char *malloc(), *realloc();
char *strncpy();
void gette(), getde(), setde(), putte(), putde();
void unimpl();
long gettw();
ef_fids mainfile;
/*
* Oops! out of memory.....
*/
void nomem()
{
(void) fprintf(stderr, "Sorry - run out of memory\n");
exit(255);
}
/*
* Look up hash value of symbol.
*/
unsigned shash(str)
register char *str;
{
register unsigned result = 0;
register int cnt = 0;
while (*str && cnt < MAXCHARS) {
result += *str++;
cnt++;
}
return result % HASHMOD;
}
/*
* Look up hash value of symbol, possibly allocating a new symbol.
*/
symbol lookup(str)
char *str;
{
register symbol res, *pp;
register int len;
pp = &symbhash[shash(str)];
res = *pp;
while (res != NULL) {
if (strncmp(res->s_name, str, MAXCHARS) == 0)
return res;
pp = &res->s_next;
res = *pp;
}
for (len = 0; len < MAXCHARS; len++)
if (str[len] == '\0')
break;
len++;
res = (symbol) malloc(sizeof(struct symstr) + len);
if (res == NULL)
nomem();
*pp = res;
res->s_next = NULL;
(void) strncpy(res->s_name, str, len);
res->s_name[len] = '\0'; /* Null-terminate */
res->s_newsym = 1;
res->s_glob = 0;
res->s_invent = 0;
res->s_link = NULL;
res->s_used = 0;
res->s_defs = 0;
res->s_lsymb = 0;
return res;
}
/*
* Invent a symbol, making sure that we don't know it.
*/
symbol inventsymb(prefix)
char *prefix;
{
static int nsymb = 0;
char schars[10];
register symbol res;
do (void) sprintf(schars, "%s%d", prefix, ++nsymb);
while (!(res = lookup(schars))->s_newsym);
res->s_newsym = 0;
res->s_invent = 1;
return res;
}
/*
* Reallocate symbol table.
*/
void reallst(outf)
register ef_fid outf;
{
outf->ef_stmax += STINC;
if (outf->ef_stvec == NULL)
outf->ef_stvec = (symbol *) malloc(outf->ef_stmax * sizeof(symbol));
else
outf->ef_stvec = (symbol *) realloc(outf->ef_stvec,
outf->ef_stmax * sizeof(symbol));
if (outf->ef_stvec == NULL)
nomem();
}
/*
* Search through existing symbol table for symbol with given
* value. Invent a new one if needed.
*/
symbol getnsymb(fid, seg, pos)
register ef_fid fid;
unsigned seg;
long pos;
{
register int i;
register symbol res;
/*********** MACHINE DEPENDENT ******************************
* Convert relocation segment type (argument) to symbol type
* (as remembered in symbol table). Don't ask me why they
* have to be different.....
*/
/*
* See if the reference is to an external symbol.
* If so, use that.
*/
for (i = 0; i < fid->ef_stcnt; i++) {
res = fid->ef_stvec[i];
if (res->s_type == seg && res->s_value == pos)
return res;
}
/*
* Invent a symbol and use that.
*/
res = inventsymb("RS");
if (fid->ef_stcnt >= fid->ef_stmax)
reallst(fid);
fid->ef_stvec[fid->ef_stcnt++] = res;
res->s_type = seg;
res->s_value = pos;
if (seg == S_TEXT) {
t_entry tent;
gette(fid, pos, &tent);
tent.t_bdest = 1;
tent.t_lab = res;
putte(fid, pos, &tent);
}
else if (seg == S_DATA || seg == S_BSS) {
d_entry dent;
getde(fid, pos, &dent);
dent.d_lab = res;
putde(fid, pos, &dent);
}
return res;
}
/*
* Assuming address given is in text segment, find its label, or invent
* one. Also set where refered from.
*/
symbol textlab(loc, refpos)
long loc, refpos;
{
t_entry tent;
gette(&mainfile, loc, &tent);
if (tent.t_type == T_CONT)
return NULL;
if (tent.t_lab == NULL) {
tent.t_lab = inventsymb("TS");
tent.t_lab->s_type = S_TEXT;
tent.t_lab->s_value = loc;
tent.t_bdest = 1;
putte(&mainfile, loc, &tent);
}
else
tent.t_lab->s_used++;
if (tent.t_refhi < refpos) {
tent.t_refhi = refpos;
putte(&mainfile, loc, &tent);
}
if (tent.t_reflo > refpos) {
tent.t_reflo = refpos;
putte(&mainfile, loc, &tent);
}
return tent.t_lab;
}
/*
* Note references to data.
*/
void mkdref(tpos, size)
long tpos;
unsigned size;
{
t_entry tent;
d_entry dent;
register symbol ds;
int dchng = 0;
int wsize;
long dpos;
gette(&mainfile, tpos, &tent);
if (tent.t_relsymb != NULL)
return;
dpos = gettw(&mainfile, tpos, R_LONG);
if (dpos < mainfile.ef_dbase || dpos > mainfile.ef_end)
return;
switch (size) {
default:
wsize = D_BYTE;
break;
case 2:
wsize = D_WORD;
break;
case 4:
wsize = D_LONG;
break;
}
getde(&mainfile, dpos, &dent);
if ((ds = dent.d_lab) == NULL) {
if (dpos >= mainfile.ef_bbase) {
ds = inventsymb("BS");
ds->s_type = S_BSS;
}
else {
ds = inventsymb("DS");
ds->s_type = S_DATA;
}
ds->s_value = dpos;
dent.d_lab = ds;
dchng++;
}
else
ds->s_used++;
if (dent.d_type != D_BYTE) {
if (dent.d_type != wsize) {
if (dent.d_type == D_ADDR) {
if (wsize != D_LONG)
unimpl("Addr word usage");
}
else if (dent.d_type > wsize) {
dchng++;
dent.d_type = wsize;
dent.d_lng = size;
}
}
}
else {
dent.d_type = wsize;
dent.d_lng = size;
dchng++;
}
if (dchng) {
putde(&mainfile, dpos, &dent);
for (dchng = 1; dchng < size; dchng++)
setde(&mainfile, dpos+dchng, D_CONT, 1);
}
tent.t_relsymb = ds;
putte(&mainfile, tpos, &tent);
}
/*
* Add item to common or abs list.
*/
#define COMINC 10
void addit(cp, symb)
register struct commit *cp;
symbol symb;
{
if (cp->c_int >= cp->c_max) {
cp->c_max += COMINC;
if (cp->c_symb == NULL)
cp->c_symb = (symbol *) malloc(COMINC*sizeof(symbol));
else
cp->c_symb = (symbol *)
realloc(cp->c_symb,
cp->c_max * sizeof(symbol));
if (cp->c_symb == NULL)
nomem();
}
cp->c_symb[cp->c_int++] = symb;
}